Micron Document
πŸŽ–οΈGitΠ―Ρ€Π°πŸŽ–οΈ


Displaying Rendered β€’ View raw β€’ Download

specs/20260711-153545-message-markdown-styling/pr-description.md bc4e9da3ad7a2a22768cbaecc75810e018bc40e2 (bc4e9da3) Text, 4.12 KB

Message inline markdown styling (iOS parity)

Why

Because iOS transmits raw markdown delimiters over the mesh (styling is presentation-only β€” there is no separate formatted payload), every Android user in a channel with an iOS 18+ user already receives messages full of literal T383838**asterisks** and T383838~~tildes~~ today, and renders them as garbled literal text. Closing the render gap is the higher-value, lower-risk half of parity; the authoring half (a formatting toolbar + live in-field styling) matches the iOS compose editor.

Cross-platform reference: meshtastic-apple PR #1771.

What

Inline markdown β€” bold, italic, ~~strikethrough~~, T383838inline code, and T383838LINK0 β€” rendered in bubbles and authorable from the compose field. All logic lives in shared T383838commonMain, so Android and desktop get one implementation. Delivered as three internally-staged user stories (single PR):

🌟 New
β€’ Render (US1): message bubbles now render the five inline styles with delimiters removed; existing autolinking, T383838@-mention resolution, and reply/search behavior are preserved. Parse failures fall back to plain autolinked text; emoji-only messages short-circuit parsing unchanged.
β€’ Toolbar (US2): a 5-button formatting row (bold/italic/strikethrough/code/link) over the compose field β€” shown on focus with β‰₯3 characters. Selection wrap/toggle, collapsed-cursor insert, and a link-entry dialog (wrap / unwrap) mirror the iOS T383838MarkdownFormatting rules byte-for-byte.
β€’ Live in-field styling (US3): the draft styles live in the field via a markdown T383838OutputTransformation composed with the existing mention transformation β€” display-only, never mutating the stored T383838TextFieldState.text.

πŸ› οΈ Changes
β€’ New direct dependency T383838org.jetbrains:markdown (0.7.5) in T383838core/ui β€” pins the version already resolved transitively via T383838multiplatform-markdown-renderer 0.43.0, so no new resolved artifact.
β€’ T383838AutoLinkText.buildAnnotatedStringWithLinks extended to interleave mention β†’ markdown-style β†’ markdown-link β†’ bare-autolink spans in one display-space coordinate system.
β€’ Four new T383838ic_format_*/T383838ic_code drawables on the house 960-grid Material Symbols convention (matching the neighboring T383838ic_link).

Notes / scope boundaries
β€’ Wire format unchanged β€” Android continues to send exactly what the user typed (raw delimiters), matching iOS. No protobuf and no database changes.
β€’ Search divergence (intentional): while a message search is active, bubbles render plain text + query highlight only (no markdown), per the clarified spec.
β€’ Block-level markdown (headers, lists, tables, code fences) is explicitly out of scope β€” iOS is inline-only; the catalog's T383838multiplatform-markdown-renderer is a block renderer and the wrong tool for chat bubbles.
β€’ Channel-URL tap interception is deferred to a separate story.

Testing Performed
β€’ T383838:core:ui T383838commonTest β€” T383838InlineMarkdownTest (parser contract, P-1…P-11) and T383838AutoLinkTextRenderTest (render contract, A-1…A-8).
β€’ T383838:feature:messaging T383838commonTest β€” T383838MessageFormattingTest (formatting-helper contract F-1…F-9, including iOS parity fixtures for byte-identical output).
β€’ Baseline: T383838spotlessApply spotlessCheck detekt assembleDebug kmpSmokeCompile β€” green.
β€’ Live on-device verify (fdroid-debug on an emulator + meshcon replay):
β€’ US1 render β€” injected T383838Meet at **noon** by the ~~old~~ new *bridge* β€” \README\T383838 and LINK0; the bubble rendered noon=bold, old=strikethrough, bridge=italic, README=monospace, map=blue tappable link, with all delimiters stripped.
β€’ US2 toolbar β€” appears on focus (β‰₯3 chars) with all five buttons; tapping Bold on a selection wrapped it to T383838**testa** with the selection growing to cover the delimiters (iOS behavior).
β€’ US3 live styling β€” typing T383838hello**world** styled "world" bold live in the field while the raw T383838** stayed visible and the byte counter tracked the raw text (transform is display-only).

Served by rngit 1.5.4 - Generated in 0.02s